package jscinttools.utilities.jhplotutilities;

import hep.aida.*;
import java.io.*;
import java.lang.*;
import java.text.DecimalFormat;

import jhplot.io.*;
import jhplot.jadraw.*;
import jhplot.*;

/**
 *  Some static methods for plotting
 *
 *@author     Marc-Antoine Verdier
 *@created    18 septembre 2010
 */
public class PlotUtil
{
	///**
	// *  The main program for the HPlotJaUtil class
	// *
	// *@param  argv  The command line arguments
	// */
	//public static void main(String[] argv)
	//{
	//	PlotUtil pu = new PlotUtil();
	//	System.out.println("That's all folks !");
	//}


	/**
	 *  Constructor for the HPlotJaUtil object
	 */
	private PlotUtil() { }

	public static P1D logFunc(F1D f){
		double min = f.getMin();
		double max = f.getMax();
		double pt = f.getPoints();
		P1D p = new P1D(f.getTitle());
		for (int i = -1; i < pt + 1; i++){
			double step = i * (Math.log10(max) - Math.log10(min));
			double exp = step / pt + Math.log10(min);
			double x = Math.pow(10.0, exp);
			double y = f.eval(x);
			p.add(x, y);
		}
		//p.setColor(f.getColor());
		p.setStyle("l");
		p.setDrawSymbol(false);
		p.setDrawOption(f.getLineParm());
		return p;
	}

	/**
	 *  Gets the bestLogAxisLim attribute of the ScintillationAnalysisPlotter_BGO
	 *  object
	 *
	 *@param  theHisto  Description of the Parameter
	 *@return           The bestLogAxisLim value
	 */
	public static double[] getBestLogAxisLim(IHistogram1D theHisto)
	{
		double[] axisLim = {0, 0};
		double minLim = theHisto.minBinHeight();
		double maxLim = theHisto.maxBinHeight();
		if (maxLim > 0 && minLim >= 0)
		{
			if (maxLim > 1)
			{
				axisLim[1] = Math.pow(10, Math.floor(Math.log10(maxLim)) + 1);
			}
			else if (maxLim == 1)
			{
				axisLim[1] = 1;
			}
			else if (maxLim < 1)
			{
				axisLim[1] = Math.pow(10, -1 * (Math.ceil(Math.log10(maxLim))));
			}

			if (minLim > 1)
			{
				axisLim[0] = Math.pow(10, Math.floor(Math.log10(minLim)));
			}
			else if (minLim < 1 && minLim > 0)
			{
				axisLim[0] = Math.pow(10, -1 * Math.ceil(Math.abs(Math.log10(minLim))));
			}
			else if (minLim == 1)
			{
				axisLim[0] = 0.1;
			}
			else
			{
				axisLim[0] = Math.pow(10, Math.log10(axisLim[1]) - 5);
			}
		}
		else
		{
			axisLim[0] = 0.1;
			axisLim[1] = 1;
		}
		return axisLim;
	}


	/**
	 *  Gets the bestLogAxisLim attribute of the ScintillationAnalysisPlotter_BGO
	 *  object
	 *
	 *@param  theDPS  Description of the Parameter
	 *@param  coord   Description of the Parameter
	 *@return         The bestLogAxisLim value
	 */
	public static double[] getBestLogAxisLim(IDataPointSet theDPS, int coord)
	{
		double[] axisLim = {0, 0};
		double minLim = theDPS.lowerExtent(coord);
		double maxLim = theDPS.upperExtent(coord);
		if (maxLim > 0 && minLim >= 0)
		{
			if (maxLim > 1)
			{
				axisLim[1] = Math.pow(10, Math.floor(Math.log10(maxLim)) + 1);
			}
			else if (maxLim == 1)
			{
				axisLim[1] = 1;
			}
			else if (maxLim < 1)
			{
				axisLim[1] = Math.pow(10, -1 * (Math.ceil(Math.log10(maxLim))));
			}
			//System.out.println("axisLim[1]=" + axisLim[1]);

			if (minLim > 1)
			{
				axisLim[0] = Math.pow(10, Math.floor(Math.log10(minLim)));
			}
			else if (minLim < 0.9999 && minLim > 0)
			{
				axisLim[0] = Math.pow(10, -1 * Math.ceil(Math.abs(Math.log10(minLim))));
			}
			else if (minLim == 1 || (minLim < 1 && minLim >= 0.9999))
			{
				axisLim[0] = 0.8;
			}
			else
			{
				axisLim[0] = Math.pow(10, Math.log10(axisLim[1]) - 5);
			}
		}
		else
		{
			axisLim[0] = 0.1;
			axisLim[1] = 1;
		}
		return axisLim;
	}


	/**
	 *  Gets the bestLogAxisLim attribute of the ScintillationAnalysisPlotter_BGO
	 *  object
	 *
	 *@param  theVal  Description of the Parameter
	 *@return         The bestLogAxisLim value
	 */
	public static double[] getBestLogAxisLim(double[][] theVal)
	{
		double[] axisLim = {0, 0};
		double minVal = theVal[0][0];
		double maxVal = theVal[0][0];
		for (int i = 0; i < theVal.length; i++)
		{
			for (int j = 0; j < theVal[0].length; j++)
			{
				if (theVal[i][j] < minVal)
				{
					minVal = theVal[i][j];
				}
				if (theVal[i][j] > maxVal)
				{
					maxVal = theVal[i][j];
				}
			}
		}
		axisLim[0] = minVal;
		axisLim[1] = maxVal;
		return axisLim;
	}


	/**
	 *  Gets the bestLinAxisLimMax attribute of the
	 *  ScintillationAnalysisPlotter_BGO object
	 *
	 *@param  theHisto  Description of the Parameter
	 *@return           The bestLinAxisLimMax value
	 */
	public static double getBestLinAxisLimMax(H1D theHisto)
	{
		double axisLim = 0;
		double hMax = theHisto.maxBinHeight();
		double dec = Math.pow(10, Math.floor(Math.abs(Math.log10(hMax))));
		double base = Math.floor(hMax / (double) dec);
		if ((hMax / (double) dec) < (base + 0.5))
		{
			axisLim = (base + 1) * dec;
		}
		else
		{
			axisLim = (base + 1.5) * dec;
		}
		return axisLim;
	}


	/**
	 *  Description of the Method
	 *
	 *@param  theString  Description of the Parameter
	 *@return            Description of the Return Value
	 */
	public static String[] replaceUnderscores(String[] theString)
	{
		for (int i = 0; i < theString.length; i++)
		{
			theString[i] = theString[i].replaceAll("_", " ");
		}
		return theString;
	}


	/**
	 *  Description of the Method
	 *
	 *@param  theVal  Description of the Parameter
	 *@return         Description of the Return Value
	 */
	public static double[] roundValuesTo3Digit(double[] theVal)
	{

		for (int i = 0; i < theVal.length; i++)
		{
			double dec = 0.0;
			if (theVal[i] > 1)
			{
				dec = Math.pow(10, (long) Math.floor(Math.log10(Math.abs(theVal[i]))));
			}
			else
			{
				dec = Math.pow(10, (long) Math.ceil(Math.log10(Math.abs(theVal[i]))));
			}
			long roundVal = Math.round((theVal[i] / (double) dec) * 100.0);
			theVal[i] = roundVal / 100.0 * dec;
		}
		return theVal;
	}


	/**
	 *  Description of the Method
	 *
	 *@param  theVal  Description of the Parameter
	 *@return         Description of the Return Value
	 */
	public static double[] roundValuesTo3DigitString(double[] theVal)
	{
		for (int i = 0; i < theVal.length; i++)
		{

			DecimalFormat fmt = new DecimalFormat("#.###");
			//}
			//if (theVal[i] >= 10 && theVal[i]<100)
			//{
			//	DecimalFormat fmt = new DecimalFormat("#.###");
			//}
			//if (theVal[i] >= 1 && theVal[i]<10)
			//{
			//	DecimalFormat fmt = new DecimalFormat("#.###");
			//}
			//if (theVal[i] >= 100)
			//{
			//	DecimalFormat fmt = new DecimalFormat("#.###");
			//}
			theVal[i] = Double.parseDouble(fmt.format(theVal[i]));
		}
		return theVal;
	}


	/**
	 *  Description of the Method
	 *
	 *@param  theVal  Description of the Parameter
	 *@return         Description of the Return Value
	 */
	public static double roundValuesTo3Digit(double theVal)
	{
		double dec = 0.0;
		if (theVal > 1)
		{
			dec = Math.pow(10, (long) Math.floor(Math.log10(Math.abs(theVal))));
		}
		else
		{
			dec = Math.pow(10, (long) Math.ceil(Math.log10(Math.abs(theVal))));
		}
		long roundVal = Math.round((theVal / (double) dec) * 100.0);
		theVal = roundVal / 100.0 * dec;
		return theVal;
	}
	
	public static String formResult(double val, double err, String patern){
		DecimalFormat df = new DecimalFormat(patern);
		return df.format(val) + " &plusmn; " + df.format(err);
	}
}

